# -*- coding: utf-8 -*-
# @Time    : 2024/7/9 16:38
# @Author  : yujiahao
# @File    : 09_fastapi_request_body_field.py
# @description:请求体字段

from typing import Annotated
from fastapi import Body, FastAPI

# 注意，与从 fastapi 导入 Query，Path、Body 不同，要直接从 pydantic 导入 Field 。
from pydantic import BaseModel, Field

app = FastAPI()


class Item(BaseModel):
    '''
    技术细节

        - 实际上，Query、Path 都是 Params 的子类，而 Params 类又是 Pydantic 中 FieldInfo 的子类。
        - Pydantic 的 Field 返回也是 FieldInfo 的类实例。
        - Body 直接返回的也是 FieldInfo 的子类的对象。后文还会介绍一些 Body 的子类。
        - 注意，从 fastapi 导入的 Query、Path 等对象实际上都是返回特殊类的函数。
        - Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。

    区别总结
        使用场景：

            Field：用于 Pydantic 模型字段，主要用于请求体参数。
            Query：用于定义查询参数，主要用于 URL 查询参数。
        功能：

            Field 和 Query 都可以添加验证规则和元数据，但它们的应用场景不同。
            Field 是 Pydantic 的一部分，用于数据模型。
            Query 是 FastAPI 的一部分，用于查询参数。
        结合 Annotated：

            Annotated 提供了一种新的、更简洁的方式来结合类型注解和元数据。
    '''
    name: str
    # 声明模型属性 使用 Field 定义模型的属性
    # Field 的工作方式和 Query、Path、Body 相同，参数也相同。
    description: str | None = Field(
        default=None, title="哇呜哇呜", max_length=300
    )
    price: float = Field(gt=0, description="The price must be greater than zero")
    tax: float | None = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    results = {"item_id": item_id, "item": item}
    return results
